<script setup lang="ts">
import * as THREE from 'three';
import { onBeforeMount, onBeforeUnmount, onMounted, ref } from 'vue';
import { Engine, Scene, FreeCamera, Vector3, MeshBuilder, HemisphericLight } from '@babylonjs/core';
import t1 from '../assets/image/t1.jpg'
import j1 from '../assets/image/j2.png'
import * as TWEEN from 'three/examples/jsm/libs/tween.module.js'
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { FlyControls } from 'three/examples/jsm/controls/FlyControls.js'
import { Tween, remove, removeAll } from '@tweenjs/tween.js';
const bjsCanvas = ref<HTMLCanvasElement | null>(null);
const threeContainer = ref<HTMLDivElement>();

onMounted(() => {
  // initThree();
  // animate(); 

  // 1. 创建一个场景
  const scene = new THREE.Scene();

  const width = window.innerWidth;
  const height = window.innerHeight;

  function createPath(pointsArr: any) {
    // 将参数数组转换成点数组的形式
    pointsArr = pointsArr.map((point: any) => new THREE.Vector3(...point));
    // 自定义三维路径 curvePath
    const path = new THREE.CurvePath();
    for (let i = 0; i < pointsArr.length - 1; i++) {
      // 每两个点之间形成一条三维直线
      const lineCurve = new THREE.LineCurve3(pointsArr[i], pointsArr[i + 1]);
      // curvePath有一个curves属性，里面存放组成该三维路径的各个子路径
      path.curves.push(lineCurve);
    }
    return path;
  }

  const pointsArr = [
    [42, 0, 10],
    [21, 0, 10],
    [21, 0, 1],
    [-3, 0, 1],
    [-3, 0, -18],
    [-10, 0, -18],
    [-10, 0, 5],
    [1, 0, 5],
    [1, 0, 24],
    [-27, 0, 24],
    [-27, 0, 18],
    [-46, 0, 19],
    [-46, 0, -4],
    [-25, 0, -6],
    [-25, 0, -19],
    [-35, 0, -20],
    [-35, 0, -26],
    [-30, 0, -30],
    [3, 0, -30]
  ];

  const curve: any = createPath(pointsArr);

  // 2. 创建管道体
  const tubeGeometry = new THREE.TubeGeometry(curve, 1000, 0.5, 10, false);
  // 纹理贴图：一定要使用透明背景的图片，否则贴图会全部叠在一起，看不出来效果
  const texLoader = new THREE.TextureLoader();
  // 图片可以用这张：http://pic.yupoo.com/mazhenghjj/e546038d/9610773f.jpg
  const texture = texLoader.setPath('/test/src').load('/assets/image/cold1.png');
  // 允许横纵设置矩阵（人话就是可以平铺）
  texture.wrapS = THREE.RepeatWrapping
  texture.wrapT = THREE.RepeatWrapping
  texture.repeat.x = 110;
  texture.repeat.y = 1;
  texture.offset.y = 0.5;

  // 3. 创建管道材质
  const tubeMaterial = new THREE.MeshPhongMaterial({
    map: texture, // 颜色贴图
    transparent: true,
    color: 0x47d8fa,
    side: THREE.DoubleSide,
  });

  // 底部网格（可以不设置）
  const gridHelper = new THREE.GridHelper(300, 25, 0x004444, 0x004444);
  scene.add(gridHelper);

  const mesh = new THREE.Mesh(tubeGeometry, tubeMaterial);
  mesh.position.y = 35;
  mesh.position.x = 0;
  mesh.rotateZ(3.14);
  mesh.scale.set(2, 2, 2);
  // 4. 把几何体（管道）和 材质 生成的网格物体添加到场景中
  scene.add(mesh);

  // 5. 设置点光源（关键的一步，没有这一步，没法照亮材质）
  const pointLight = new THREE.PointLight(0xffffff, 1);
  // 点光源位置
  pointLight.position.set(100, 100, 100);
  scene.add(pointLight);

  // 6. 点光源辅助对象（可有可无，辅助观察光源位置，需要时放开 add 方法）
  const sphereSize = 10;
  const pointLightHelper = new THREE.PointLightHelper(pointLight, sphereSize);
  // scene.add( pointLightHelper );

  // 7. 环境光（整个场景的光，添加后整个管道都能更明亮）
  const light = new THREE.AmbientLight(0xffffff, 1);
  scene.add(light);

  // 8. 相机位置（拍照片，关键，Three的每一个帧需要拍下来才能显示）
  const camera = new THREE.PerspectiveCamera(30, width / height, 0.1, 2000);
  // 超出视锥体的远裁截面的范围会被剪掉
  camera.position.set(200, 200, 200);

  // 定义相机的视线
  camera.lookAt(100, 100, 100);

  // 9. 渲染方法
  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(width, height);
  // 用相机(camera)渲染一个场景(scene)。类比相机的拍照动作
  renderer.render(scene, camera);
  threeContainer.value?.appendChild(renderer.domElement);

  // 10. 循环
  function render() {
    // 周期性渲染，更新 canvas 画布的内容
    renderer.render(scene, camera);
    requestAnimationFrame(render);
    // 关键一步，循环改变贴图的位置，css的属性
    texture.offset.x -= 0.04;
  }

  render();

  // 11. 拖动相机位置（场景能放大、缩小、移动，其实通过更改相机位置做到的）
  const controls = new OrbitControls(camera, renderer.domElement);

  // 12. 这一步是优化，在窗口改变时，canvas 位置也跟着改变
  window.onresize = function () {
    renderer.setSize(window.innerWidth, window.innerHeight);
    // 相机宽高比
    camera.aspect = window.innerWidth / window.innerHeight;
    // 更新摄像机投影矩阵
    camera.updateProjectionMatrix();
  }

});
onBeforeUnmount(() => {

});
</script>
<template>
  <div ref="threeContainer" class="three-container"></div>
</template>
<style scoped>
.three-container {
  width: 100%;
  height: 100%;
  /* 或者你想要的高度 */
  overflow: hidden;
}
</style>